package com.mikhailenko.transportMVC.controller;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.mikhailenko.transportMVC.model.Criteria;
import com.mikhailenko.transportMVC.model.Firm;
import com.mikhailenko.transportMVC.model.Group;
import com.mikhailenko.transportMVC.model.OperationEnum;
import com.mikhailenko.transportMVC.model.Table;
import com.mikhailenko.transportMVC.model.TableForm;
import com.mikhailenko.transportMVC.service.CriteriaService;
import com.mikhailenko.transportMVC.service.FirmService;
import com.mikhailenko.transportMVC.service.GroupService;
import com.mikhailenko.transportMVC.utils.Convertor;
import com.mikhailenko.transportMVC.utils.Nmai;
import com.mikhailenko.transportMVC.utils.TableUtil;
import com.mikhailenko.transportMVC.validator.FuzzyTableValidator;

@Controller
@RequestMapping(value = "/table-group")
public class TableGroupController {

    @Autowired
    private Nmai nmai;

    @Autowired
    private FirmService firmService;

    @Autowired
    private FuzzyTableValidator tableValidator;

    @Autowired
    private TableUtil tableUtil;

    @Autowired
    private CriteriaService criteriaService;

    @Autowired
    private GroupService groupService;

    @InitBinder("tableForm")
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(tableValidator);
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public ModelAndView createTableGroupPage() {
        ModelAndView mav = new ModelAndView("table-group", "tableForm", new TableForm());

        List<Firm> firms = firmService.findAll();
        mav.addObject("firms", firms);

        List<Criteria> criteria = criteriaService.findAll();
        mav.addObject("criteria", criteria);

        List<Group> groups = groupService.findAll();
        mav.addObject("groups", groups);

        List<List<Criteria>> criteriaForGroup = new ArrayList<List<Criteria>>();
        for (Group group : groups) {
            criteriaForGroup.add(criteriaService.findByGroup(group.getId()));
        }
        mav.addObject("criteriaForGroup", criteriaForGroup);

        return mav;
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public ModelAndView createNewTable(@ModelAttribute @Valid TableForm tableForm, BindingResult result,
            final RedirectAttributes redirectAttributes) {

        List<Group> groups = groupService.findAll();

        List<List<Criteria>> criteriaForGroup = new ArrayList<List<Criteria>>();
        for (Group group : groups) {
            criteriaForGroup.add(criteriaService.findByGroup(group.getId()));
        }

        if (result.hasErrors()) {
            ModelAndView mav = new ModelAndView("table-group");

            List<Firm> firms = firmService.findAll();
            mav.addObject("firms", firms);

            List<Criteria> criteria = criteriaService.findAll();
            mav.addObject("criteria", criteria);

            mav.addObject("groups", groups);
            mav.addObject("criteriaForGroup", criteriaForGroup);

            return mav;
        }

        ModelAndView mav = new ModelAndView();
        for (int i = 0; i < tableForm.getTableList().size(); i++) {
            Table table = tableForm.getTableList().get(i);

            List<String> rowSum = new ArrayList<String>();
            String detetminedVector = null;
            List<String> multiplication = new ArrayList<String>();
            List<String> priorityVector = new ArrayList<String>();
            List<List<String>> desicionTable = tableUtil.fill(table.getTable());
            table.setTable(desicionTable);

            if (table.getOperation().equals(OperationEnum.EXTENT_ANALYSIS)) {
                double[][] rowS = nmai.getRowSum(desicionTable);
                rowSum = Convertor.triangleMasToList(rowS);
                table.setRowSum(rowSum);

                double[] detVector = nmai.getDeterminedVectorInverce(desicionTable);
                detetminedVector = Convertor.singleMasToString(detVector);
                table.setDetetminedVector(detetminedVector);

                double[][] mul = nmai.getFuzzyMultiplication(rowS, detVector);
                multiplication = Convertor.triangleMasToList(mul);
                table.setMultiplication(multiplication);

                double[] vector = nmai.getPriorityVector(mul);
                priorityVector = Convertor.masToList(vector);
                table.setPriorityVector(priorityVector);

            } else {
                // TODO: need implement other methods
            }
        }

        mav.setViewName("redirect:/table-group/result");

        TableForm groupResult = getGroupResultMain(tableForm, groups, criteriaForGroup);
        Table mainResult = nmai.getResultTable(groupResult);
        
        redirectAttributes.addFlashAttribute("tableResult", tableForm);
        redirectAttributes.addFlashAttribute("mainResult", mainResult);
        redirectAttributes.addFlashAttribute("groupResult", groupResult);
        
        return mav;
    }

    @RequestMapping(value = "/result", method = RequestMethod.GET)
    public ModelAndView newResultPage(@ModelAttribute("tableResult") final TableForm tableForm,
            @ModelAttribute("mainResult") final Table mainResult,
            @ModelAttribute("groupResult") final TableForm groupResult) {
        
        ModelAndView mav = new ModelAndView("table-group-result", "tableResult", tableForm);

        List<Firm> firms = firmService.findAll();
        mav.addObject("firms", firms);

        List<Criteria> criteria = criteriaService.findAll();
        mav.addObject("criteria", criteria);

        List<Group> groups = groupService.findAll();
        mav.addObject("groups", groups);

        List<List<Criteria>> criteriaForGroup = new ArrayList<List<Criteria>>();
        for (Group group : groups) {
            criteriaForGroup.add(criteriaService.findByGroup(group.getId()));
        }
        
        mav.addObject("criteriaForGroup", criteriaForGroup);
        mav.addObject("groupResult", groupResult);
        mav.addObject("mainResult", mainResult);
        
        return mav;
    }
    
    @RequestMapping(value="/hierarchy", method=RequestMethod.GET)
    public ModelAndView newHierarchyPage(){
        ModelAndView mav = new ModelAndView("table-group-hierarchy");
        
        List<Firm> firms = firmService.findAll();
        mav.addObject("firms", firms);

        List<Criteria> criteria = criteriaService.findAll();
        mav.addObject("criteria", criteria);

        List<Group> groups = groupService.findAll();
        mav.addObject("groups", groups);

        List<List<Criteria>> criteriaForGroup = new ArrayList<List<Criteria>>();
        for (Group group : groups) {
            criteriaForGroup.add(criteriaService.findByGroup(group.getId()));
        }
        mav.addObject("criteriaForGroup", criteriaForGroup);
        
        return mav;
    }
    
    private TableForm getGroupResultMain(TableForm tableForm, List<Group> groups, List<List<Criteria>> criteriaForGroup) {
        TableForm groupResultMain = new TableForm();
        List<Table> temp = new ArrayList<Table>();
        groupResultMain.setTableList(temp);
        groupResultMain.getTableList().add(tableForm.getTableList().get(0));
        
        int index = 1;
        for (int i = 0; i < groups.size(); i++) {
            TableForm groupResult = new TableForm();
            List<Table> temp2 = new ArrayList<Table>();
            groupResult.setTableList(temp2);
            groupResult.getTableList().add(tableForm.getTableList().get(index));
            index++;
            for (int j = 0; j < criteriaForGroup.get(i).size(); j++) {
                groupResult.getTableList().add(tableForm.getTableList().get(index));
                index++;
            }
            Table mainResult = nmai.getResultTable(groupResult);
            groupResultMain.getTableList().add(mainResult);
        }

        return groupResultMain;
    }
}
